#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include"protocol.hpp"
using namespace std;
#define NUM 1024
namespace client
{

    class calclient
{

public:
calclient(const string& ip,const uint16_t& port)
:_sock(-1)
,_port(port)
,_ip(ip)
{}

void initclient()
{
//1.创建sockfd
_sock=socket(AF_INET,SOCK_STREAM,0);
if(_sock<0)
{
   cerr<<"socket create error"<<endl;
   exit(2);
}
//2.绑定 ip port，不显示绑定，OS自动绑定
}

void start()
{
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
socklen_t len=sizeof(ser);
ser.sin_family=AF_INET;
ser.sin_port=htons(_port);
ser.sin_addr.s_addr=inet_addr(_ip.c_str());
if(connect(_sock,(struct sockaddr *)&ser,len)!=0)
{
    cerr<<"connect error"<<endl;
}else
{
    string line;
    string inbuffer;
    while(true)
    {
        cout<<"mycal>>: ";//输入"xopy"
        getline(cin,line);
        Request req=ParseLine(line);//用"xopy"取出x op y构造Request对象
        string context;
        req.Serialize(&context);//序列化，用x op y构造字符串"xSEPopSEPy"
        string send_str=enLength(context);//定制协议---"x op y"->"text_len"\r\n"x op y"\r\n---給内容加上报头
        cout<<"calclient send str: "<<send_str<<endl;
        send(_sock,send_str.c_str(),send_str.size(),0);//客户端把报文发送給服务器

        string package;
        if(!recvPackage(_sock,inbuffer,&package)) continue;//服务器处理完数据，客户端接收服务器发送来的报文
        //  "content_len"\r\n"exitcode result"\r\n
        string reser_len;
        if(!deLength(package,&reser_len)) continue;//去报头
         //  "content_len"\r\n"exitcode result"\r\n -> "exitcode result"
        Response rep;
        rep.Deserialize(reser_len);//反序列化：//_exitcodeSEP_result"->_exitcode _result

        cout<<"_exitcode: "<<rep._exitcode<<endl;
        cout<<"_result: "<<rep._result<<endl;
    }
}
}

~calclient()
{
    if(_sock>=0) close(_sock);
}

Request ParseLine(const string& line)
{//"xopy"->取出来到x op y 上
int i=0;
int status=0;
int num=line.size();
string left,right;
char op;

while(i<num)
{
switch(status)
{
    case 0:
    {
        if(!isdigit(line[i]))
    {
        op=line[i];//取出运算符**
        status=1;
    }else
    left.push_back(line[i++]);//取出左操作数
    }
    break;
    case 1:
    i++;
    status=2;
    break;

    case 2:
    right.push_back(line[i++]);
    break;
}
}
cout<<"left: "<<stoi(left)<<" op: "<<op<<" right: "<<stoi(right)<<endl;
return Request(stoi(left),stoi(right),op);//返回Request对象

}

private:
int _sock;
uint16_t _port;
string _ip;

};
}

